Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 << zurück
Visual C# 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2005

Visual C# 2005
1.320 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-586-X
gp Kapitel 5 Das Klassendesign (Teil 2)
  gp 5.1 Statische Klassenkomponenten
    gp 5.1.1 Die Realisierung eines Objektzählers
    gp 5.1.2 Zugriff auf statische Komponenten
    gp 5.1.3 Statische Klassenvariable in der Klasse »Circle«
    gp 5.1.4 Klassenspezifische Methoden
    gp 5.1.5 Statische Methoden in der Klasse »Circle«
    gp 5.1.6 Statische Klasseninitialisierer
    gp 5.1.7 Statische Klassen
    gp 5.1.8 Zusammenfassung
  gp 5.2 Delegate – Methodenzeiger unter .NET
    gp 5.2.1 Einführung in das Prinzip der Delegate
    gp 5.2.2 Zusammenfassung der Arbeitsschritte
    gp 5.2.3 Vereinfachter Aufruf eines Delegaten
    gp 5.2.4 Anonyme Methoden
  gp 5.3 Ereignisse eines Objekts
    gp 5.3.1 Ergänzung eines Ereignisses in einer Ereignisquelle
    gp 5.3.2 Die Behandlung eines Ereignisses im Ereignisempfänger
    gp 5.3.3 Wenn der Ereignisempfänger ein Ereignis nicht behandelt
    gp 5.3.4 Ereignisse mit Übergabeparameter
    gp 5.3.5 Zusammenfassung
  gp 5.4 Strukturen – eine Sonderform der Klassen
    gp 5.4.1 Die Definition einer Struktur
    gp 5.4.2 Initialisieren einer Struktur
    gp 5.4.3 Weitere Merkmale einer Struktur
    gp 5.4.4 Verschachtelung von Strukturen
    gp 5.4.5 Änderung der Klasse »Circle«
    gp 5.4.6 Zusammenfassung
  gp 5.5 Enumerationen (Aufzählungen)
    gp 5.5.1 Wertzuweisung an enum-Mitglieder
    gp 5.5.2 Alle Mitglieder einer Aufzählung durchlaufen
  gp 5.6 Referenz- und Wertetypen
    gp 5.6.1 Typumwandlung mit Boxing
    gp 5.6.2 Die Unboxing-Konvertierung
    gp 5.6.3 Zusammenfassung
  gp 5.7 Namensräume (Namespaces)
    gp 5.7.1 Zugriff auf Namespaces
    gp 5.7.2 Die »using«-Direktive
    gp 5.7.3 Vermeiden von Mehrdeutigkeiten
    gp 5.7.4 Aufrufe mit dem »::«-Operator umleiten
    gp 5.7.5 Namespaces festlegen
    gp 5.7.6 Zusammenfassung


Galileo Computing

5.6 Referenz- und Wertetypedowntop

Das .NET-Typsystem setzt sich aus zwei Subsystemen zusammen:

gp  Wertetypen
gp  Referenztypen

Zu den Wertetypen werden primitive Datentypen wie int und long sowie die in den beiden vorhergehenden Abschnitten behandelten Strukturen und Enumerationen gezählt, zu den Referenztypen der Typ string, alle Arrays und – ganz allgemein ausgedrückt – alle klassenbasierten Objekte. Obwohl es im ersten Augenblick den Anschein haben mag, dass hinter Wertetypen nur »normale« Dateninformationen stehen, werden auch diese als Objekte angesehen und hinter den Kulissen der .NET-Laufzeit als solche behandelt. Der Unterschied zwischen Referenz- und Wertetypen ist vielmehr in der Allokierung des Systemspeichers zu finden.

Eine Variable, die einen Wertetyp repräsentiert, allokiert auf dem Stack Speicher für die Daten. Der Stack ist im RAM angesiedelt, wird aber vom Prozessor durch einen so genannten Stack Pointer direkt unterstützt. Dieser ist in der Lage, auf dem Stack neuen Speicher zu reservieren, kann ihn aber auch freigeben. Dieses Verfahren ist sehr effizient und schneller als das Allokieren von Speicher im Heap für Referenztypen.

Als Heap wird der Speicher im RAM bezeichnet, der allgemeinen Zwecken zur Verfügung steht. Dazu gehören auch die Zustandsdaten eines Objekts. Der Compiler weiß nicht, wie viel Speicher er zur Laufzeit eines Programms im Heap allokieren muss und wie lange die Allokierung aufrechterhalten bleibt. Das garantiert natürlich ein hohes Maß an Flexibilität, da zur Laufzeit eine zur Entwicklungszeit nicht vorhersehbare Anzahl von Objekten erzeugt werden kann. Die Flexibilität gibt es jedoch nicht kostenlos: Es dauert etwas länger, auf dem Heap Speicher zu reservieren.

Wird mit


int intVar = 100;

eine int-Variable deklariert, schreibt sich der 32-Bit-Wert in den Stack. Beachten Sie bitte, dass bei einem Wertetyp der new-Operator zur Initialisierung nicht angegeben werden muss – bei einem Referenztyp ist das eine unabdingbare Forderung, denn erst mit


Circle kreis = new Circle();

wird auf dem Heap ein Speicherbereich allokiert und initialisiert, auf den danach die Referenz kreis zeigt.

Ein daraus folgendes, wichtiges Unterscheidungsmerkmal zwischen Referenz- und Wertetypen ist, dass Wertetypen niemals den Inhalt null haben können. Wenn mit


Circle kreis;

eine auf einer Klasse basierende Objektvariable deklariert wird, ohne mit new initialisiert zu werden, ist deren Inhalt null.

Bemerkenswert ist die unterschiedliche Wirkungsweise des Zuweisungsoperators zwischen einem Werte- und einem Referenztyp. Betrachten Sie dazu zunächst das Codefragment eines Wertetypen:


long lngVar = 64;
long lngSecond = lngVar;

Nach der Ausführung des Codes existieren zwei Variablen vom Typ long, die denselben Inhalt haben. long wird, wie nahezu alle elementaren Datentypen, von der Common Language Runtime als Wertetyp angesehen und entsprechend behandelt. Die Änderung des Inhalts der Variablen lngVar wird sich nicht auf den Inhalt der Variablen lngSecond auswirken, weil zwischen den beiden keine Verbindung existiert.

Nun soll ein ähnliches Codefragment betrachtet werden, diesmal allerdings auf Basis eines Referenztyps.


Circle kreis1 = new Circle();
Circle kreis2 = new Circle();
kreis1.Radius = 320;
kreis2 = kreis1;
Console.WriteLine(kreis2.Radius);

In diesem Programmausschnitt werden zwei Objekte gleichen Typs erzeugt. Anschließend wird die Referenz, die auf das zweite Objekt im Speicher zeigt, auf die Adresse des ersten umgebogen. Die Ausgabe an der Konsole (= 320) beweist, dass beide Objektvariablen mit demselben Objekt im Speicher operieren. Der Zuweisungsoperator, angewandt auf Referenztypen, bewirkt demnach ein Verbiegen des Zeigers, bei Wertetypen einen Kopiervorgang.


Galileo Computing

5.6.1 Typumwandlung mit Boxing  downtop

Die Ausführungen des vorhergehenden Abschnitts scheinen im Widerspruch zu einer anderen Aussage zu stehen, die vorher schon mehrfach getroffen worden ist: Die Common Language Runtime betrachtet alles als Objekt. Wie kann aber ein Wertetyp, der definitionsgemäß Speicher im Stack und nicht auf dem Heap allokiert, als Objekt angesehen werden?

Die Antwort auf die Frage lautet: mittels eines Verfahrens, das Boxing genannt wird. Durch diese Technik wird ein Objekt erst dann zu einem solchen, wenn es auch wirklich als Objekt benötigt wird. Betrachten Sie dazu das folgende Codefragment:


class ClassA {
  public enum Spielkarte {
    Karo = 9,
    Herz,
    Pik,
    Kreuz
  }
  static void Main(string[] arr) {   
    Spielkarte myGame;
    myGame = Spielkarte.Karo;
    Console.WriteLine("Wert = {0}", myGame);
  }
}

 

 

Die Ausführung des Programms wird an der Konsole die Ausgabe


Wert = Karo

haben. Wir müssen damit auch feststellen, dass der Typ Spielkarte von der Methode WriteLine erkannt wird und zu einer korrekten Ausgabe führt. Sie können in der .NET-Dokumentation nachschlagen, selbstverständlich werden Sie keine passende Parameterliste der überladenen WriteLine-Methode finden, die den Typ Spielkarte angibt.

Die Technologie, die sich hinter den Kulissen der .NET-Laufzeitumgebung abspielt und zu der gewünschten Ausgabe führt, ist das Boxing. Dabei wird ein Wertetyp – und um einen solchen handelt es sich bei einer Auflistung – implizit in den Typ Object, also einen Referenztyp, konvertiert. Diese Technik wird immer dann automatisch eingesetzt, wenn ein Wertetyp verwendet wird, wo Object erforderlich wäre.

Das hört sich sehr kompliziert an, deshalb wollen wir die einzelnen Schritte anhand des Beispielcodes von oben nachvollziehen. Beim Aufruf von


Console.WriteLine("Wert = {0}", myGame);

sucht der Compiler nach einer passenden Überladung der Methode WriteLine. Er findet eine adäquate in:


public static void WriteLine(String, Object);

Der zweite Parameter ist vom Typ Object, bekommt aber eine Variable des Typs Spielkarte übergeben. Da Enumerationen von der Klasse Object abgeleitet werden, wird implizit eine Object-Referenz erzeugt und auf den Stack gelegt:


Object-Referenz = myGame

Diese Referenz verweist auf ein neues Objekt im Heap, das die kopierten Werte der auf dem Stack befindlichen Variablen myGame unter Angabe des Typs in einer Art Box enthält. Als Resultat dieser Operation liegen auf dem Stack zwei Wertetypen:

1.  das Original des Wertetyps (also myGame)
2. die Referenz auf das Object-Objekt
       

Der neue Verweis wird an die Methode WriteLine übergeben, die damit ihrerseits wieder den Inhalt auswerten kann. Die folgende Abbildung macht den Sachverhalt deutlich, dass beim Boxing die Kopie eine Wertetyps in einen Referenztyp erfolgt, damit also zwei Elemente desselben Inhalts vorliegen.

Wenn die Aussage stimmt, dass beim Boxing die Kopie eines Wertetyps erstellt wird, muss sich auch der Beweis führen lassen. Dazu wird nach der Erstellung der Kopie der Inhalt des Referenz- oder des Wertetyps verändert:


static void Main(string[] arr) {   
  int intVar = 100;
  Object intObj = intVar;
  intVar = 4711;
  Console.WriteLine("Der Inhalt von intObj = {0}", intObj);
  Console.WriteLine("Der Inhalt von intVar = {0}", intVar);
  Console.Read();
}

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 5.1   Boxing eines Wertetypen

Zuerst wird die int-Variable intVar deklariert und ihr ein Wert zugewiesen. Anschließend wird intVar in einen Object-Typ konvertiert. In der dritten Anweisung wird intVar ein anderer Wert zugewiesen. Wenn die geboxte Variable unabhängig von der auf dem Stack ist, müssen an der Konsole zwei unterschiedliche Ausgaben erfolgen. Dies wird durch


Der Inhalt von intObj = 100
Der Inhalt von intVar = 4711

tatsächlich bestätigt.


Galileo Computing

5.6.2 Die Unboxing-Konvertierung  downtop

Die Konvertierung eines Object-Typs in einen Wertetyp ist ein Rückführungsprozess und wird als Unboxing bezeichnet. Die .NET-Laufzeitumgebung prüft dabei zuerst, ob es sich wirklich um einen »geboxten« Wert eines bestimmten Typs handelt. Danach wird der Inhalt des Referenztyps in die Variable eines Wertetyps kopiert.


int intVar = 4711;
Object obj = intVar;
obj = 15;
// Unboxing
intVar = Convert.ToInt32(obj);

Natürlich gelten auch hier die bekannten Regeln der Konvertierung.


Galileo Computing

5.6.3 Zusammenfassung  toptop

gp  Enumerationen sind Aufzählungen von Konstanten gleichen Datentyps und daher zur Laufzeit nicht veränderlich.
gp  Wird einer Enumeration kein Datentyp zugeordnet, ist die Enumeration standardmäßig vom Typ int.
gp  Die Wertzuweisung an enum-Konstanten ist optional. Wird darauf verzichtet, steht das erste Element für den Wert 0, der sich mit jedem Folgeelement um +1 erhöht. Die einzelnen Elemente einer Enumeration werden voneinander durch ein Komma getrennt.
gp  Die Common Language Runtime unterscheidet Werte- und Referenztypen. Referenztypen sind alle auf Klassen basierenden Objekte sowie Strings und Arrays. Zu den Wertetypen zählen die elementaren Datentypen (int, float usw.), außerdem auch noch Strukturen und enum-Konstantenaufzählungen.
gp  Wertetypen reservieren auf dem Stack Speicher, während Referenztypen ihren Speicherbedarf im Heap allokieren.
gp  Eine Variable, die auf einem Referenztyp basiert, wird grundsätzlich mit dem new-Operator initialisiert und kann den Inhalt null haben.
gp  Von der Laufzeit werden Referenz- und Wertetypen gleich behandelt, da die Common Language Runtime alles als Objekt behandelt. Um einen Wertetyp zur Laufzeit wie ein Objekt behandeln zu können, wird er mit einem als Boxing bezeichneten Mechanismus in ein Objekt konvertiert.
 << zurück
  
  Zum Katalog
Zum Katalog: Visual C# 2005
Visual C# 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Visual Basic 2005






 Visual Basic 2005


Zum Katalog: Java ist auch eine Insel






 Java ist auch eine
 Insel


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de